package butines.game.lastcolony.entities;

import static butines.game.lastcolony.entities.EntityAction.STAND;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

import butines.core.GameImage;
import butines.game.lastcolony.entities.EntityOrders.Type;

public class Vehicle extends Entity {
    
    public static final EntityClass TRANSPORT;
    public static final EntityClass HARVESTER;
    public static final EntityClass SCOUT_TANK;
    public static final EntityClass HEAVY_TANK;
    
    static {
        TRANSPORT = new EntityClass();
        TRANSPORT.setName("Transport");
        TRANSPORT.setAction(STAND);
        TRANSPORT.setOrdersType(EntityOrders.Type.STAND);
        TRANSPORT.setSelectable(true);
        TRANSPORT.setPixelWidth(31);
        TRANSPORT.setPixelHeight(30);
        TRANSPORT.setPixelOffsetX(15);
        TRANSPORT.setPixelOffsetY(15);
        TRANSPORT.setRadius(15);
        TRANSPORT.setSpeed(15);
        TRANSPORT.setSight(3);
        TRANSPORT.setCost(400);
        TRANSPORT.setHitPoints(100);
        TRANSPORT.setTurnSpeed(2);
        TRANSPORT.setDirections(8);
        TRANSPORT.setSpriteSheet(new GameImage("images/vehicles/transport.png"));
        TRANSPORT.addEntitySprite("stand", 1, 8);
        
        HARVESTER = new EntityClass();
        HARVESTER.setName("Harvester");
        HARVESTER.setAction(STAND);
        HARVESTER.setOrdersType(EntityOrders.Type.STAND);
        HARVESTER.setSelectable(true);
        HARVESTER.setPixelWidth(21);
        HARVESTER.setPixelHeight(20);
        HARVESTER.setPixelOffsetX(10);
        HARVESTER.setPixelOffsetY(10);
        HARVESTER.setRadius(10);
        HARVESTER.setSpeed(10);
        HARVESTER.setSight(3);
        HARVESTER.setCost(1600);
        HARVESTER.setHitPoints(50);
        HARVESTER.setTurnSpeed(2);
        HARVESTER.setDirections(8);
        HARVESTER.setSpriteSheet(new GameImage("images/vehicles/harvester.png"));
        HARVESTER.addEntitySprite("stand", 1, 8);
        
        SCOUT_TANK = new EntityClass();
        SCOUT_TANK.setName("Scout tank");
        SCOUT_TANK.setAction(STAND);
        SCOUT_TANK.setOrdersType(EntityOrders.Type.STAND);
        SCOUT_TANK.setSelectable(true);
        SCOUT_TANK.setCanAttack(true);
        SCOUT_TANK.setCanAttackLand(true);
        SCOUT_TANK.setCanAttackAir(false);
        SCOUT_TANK.setWeaponType(WeaponType.BULLET);
        SCOUT_TANK.setPixelWidth(21);
        SCOUT_TANK.setPixelHeight(21);
        SCOUT_TANK.setPixelOffsetX(10);
        SCOUT_TANK.setPixelOffsetY(10);
        SCOUT_TANK.setRadius(11);
        SCOUT_TANK.setSpeed(20);
        SCOUT_TANK.setSight(4);
        SCOUT_TANK.setCost(500);
        SCOUT_TANK.setHitPoints(50);
        SCOUT_TANK.setTurnSpeed(4);
        SCOUT_TANK.setDirections(8);
        SCOUT_TANK.setSpriteSheet(new GameImage("images/vehicles/scout-tank.png"));
        SCOUT_TANK.addEntitySprite("stand", 1, 8);
        
        HEAVY_TANK = new EntityClass();
        HEAVY_TANK.setName("Heavy-tank");
        HEAVY_TANK.setAction(STAND);
        HEAVY_TANK.setOrdersType(EntityOrders.Type.STAND);
        HEAVY_TANK.setSelectable(true);
        HEAVY_TANK.setCanAttack(true);
        HEAVY_TANK.setCanAttackLand(true);
        HEAVY_TANK.setCanAttackAir(false);
        HEAVY_TANK.setWeaponType(WeaponType.CANNON_BALL);
        HEAVY_TANK.setPixelWidth(30);
        HEAVY_TANK.setPixelHeight(30);
        HEAVY_TANK.setPixelOffsetX(15);
        HEAVY_TANK.setPixelOffsetY(15);
        HEAVY_TANK.setRadius(13);
        HEAVY_TANK.setSpeed(15);
        HEAVY_TANK.setSight(5);
        HEAVY_TANK.setCost(1200);
        HEAVY_TANK.setHitPoints(50);
        HEAVY_TANK.setTurnSpeed(4);
        HEAVY_TANK.setDirections(8);
        HEAVY_TANK.setSpriteSheet(new GameImage("images/vehicles/heavy-tank.png"));
        HEAVY_TANK.addEntitySprite("stand", 1, 8);
        
    }
    
    public static Vehicle create(String name, Object ... values) {
        if ("transport".equals(name)) {
            return TRANSPORT.create(Vehicle.class, values);
        } else if ("harvester".equals(name)) {
            return HARVESTER.create(Vehicle.class, values);
        } else if ("scout-tank".equals(name)) {
            return SCOUT_TANK.create(Vehicle.class, values);
        } else if ("heavy-tank".equals(name)) {
            return HEAVY_TANK.create(Vehicle.class, values);
        }
        return null;
    }
    
    private int imageOffset;
    private int animationIndex;
    private EntitySprite imageList;
    
    public Vehicle() {
        
    }
    
    public void animate() {
        if (getLife() > getEntityClass().getHitPoints() * 0.4){
            setLifeCode("healthy");
        } else if (getLife() <= 0){
            setLifeCode("dead");
            getGame().remove(this);
            return;
        } else {
            setLifeCode("damaged");
        }

        if (getAction() == STAND) {
            imageList = getEntityClass().getEntitySprite("stand-" + (int) getDirection());
            imageOffset = this.imageList.getOffset() + animationIndex;
            animationIndex++;
            if (animationIndex >= imageList.getCount()){
                animationIndex = 0;
            }
        }
        
    }
    
    private void drawLifeBar(Graphics2D g2d, float drawingX, float drawingY) {
        int x = (int) drawingX;
        int y = (int) (drawingY - 2 * game.getLifeBarHeight());

        Color color = isHealthy() ? game.getHealthBarHealthyFillColor() : game.getHealthBarDamagedFillColor();

        g2d.setColor(color);
        g2d.fillRect(x, y, (int) (getPixelWidth() * getLife() / (float) getHitPoints()), game.getLifeBarHeight());

        g2d.setColor(game.getHealthBarBorderColor());
        g2d.drawRect(x, y, getPixelWidth(),game.getLifeBarHeight());
    }
    
    private void drawSelection(Graphics2D g2d, float drawingX, float drawingY) {
        int x = (int) drawingX + getPixelOffsetX();
        int y = (int) drawingY + getPixelOffsetY();

        g2d.setColor(game.getSelectionFillColor());
        g2d.fillOval(x - getRadius(), y - getRadius(), getRadius() * 2, getRadius() * 2);

        g2d.setColor(game.getSelectionBorderColor());
        g2d.drawOval(x - getRadius(), y - getRadius(), getRadius() * 2, getRadius() * 2);
    }

    public void draw(Graphics2D g2d) {
        float sx = (getX() * getGame().getGridSize()) - getGame().getOffsetX() - getEntityClass().getPixelOffsetX();
        float sy = (getY() * getGame().getGridSize()) - getGame().getOffsetY() - getEntityClass().getPixelOffsetY();
       
        int colorIndex = getTeam() == EntityTeam.BLUE ? 0 : 1;
        int colorOffset = colorIndex * getEntityClass().getPixelHeight();
        
        int ix = imageOffset * getEntityClass().getPixelWidth();
        int iy = colorOffset;
        int iw = getEntityClass().getPixelWidth();
        int ih = getEntityClass().getPixelHeight();
        
        if (isSelected()) {
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            drawSelection(g2d, sx, sy);
            drawLifeBar(g2d, sx, sy);
        }
        
        getEntityClass().getSpriteSheet().draw(g2d, (int) sx, (int) sy, ix, iy, iw, ih);
    }
    
    private float lastMovementX = 0;
    private float lastMovementY = 0;

    public void processOrders() {
        lastMovementX = 0;
        lastMovementY = 0;
        switch (orders.getType()) {
            case MOVE:
                // Move towards destination until distance from destination is less than vehicle radius
                float x = orders.getX() - this.x;
                float y = orders.getY() - this.y;
                float r = getRadius() / getGame().getGridSize();
                // Move towards destination until distance from destination is less than aircraft radius
                float distanceFromDestinationSquared = (x * x + y * y);
                if (distanceFromDestinationSquared <= (r * r)) {
                    orders.setType(Type.STAND);
                    return;
                } else {
                    // Try to move to the destination
                    boolean moving = moveTo(orders.getX(), orders.getY());
                    if (!moving) {
                        // Pathfinding couldn't find a path so stop
                        orders.setType(Type.STAND);
                        return;
                    }
                }
                break;
        }
    }

    private boolean moveTo(float x, float y) {
        game.rebuildPassableGrid();
        return false;
    }
    
}
